"""
文件监控模块
使用 watchdog 监控文件系统变化
"""
import os
import time
import threading
from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler, FileSystemEvent
from typing import Callable
from sync_engine import SyncEngine


class SyncFileEventHandler(FileSystemEventHandler):
    """文件系统事件处理器"""
    
    def __init__(self, sync_engine: SyncEngine, callback: Callable = None):
        super().__init__()
        self.sync_engine = sync_engine
        self.callback = callback
        self.pending_events = {}  # 用于去重和延迟处理
        self.lock = threading.Lock()
    
    def _log(self, message: str, level: str = "INFO"):
        """记录日志"""
        if self.callback:
            self.callback(message, level)
    
    def _process_event(self, event: FileSystemEvent):
        """处理文件系统事件（延迟执行）"""
        # 忽略目录事件，只处理文件
        if event.is_directory:
            return
        
        with self.lock:
            # 记录事件，延迟处理（避免频繁操作）
            self.pending_events[event.src_path] = (event.event_type, time.time())
    
    def on_created(self, event):
        """文件创建事件"""
        self._process_event(event)
    
    def on_modified(self, event):
        """文件修改事件"""
        self._process_event(event)
    
    def on_deleted(self, event):
        """文件删除事件"""
        if not event.is_directory:
            self._log(f"检测到文件删除: {event.src_path}")
            self.sync_engine.sync_delete(event.src_path)
    
    def on_moved(self, event):
        """文件移动事件"""
        if not event.is_directory:
            self._log(f"检测到文件移动: {event.src_path} -> {event.dest_path}")
            # 处理为删除旧文件 + 创建新文件
            self.sync_engine.sync_delete(event.src_path)
            time.sleep(0.1)  # 短暂延迟
            if os.path.exists(event.dest_path):
                self.sync_engine.sync_file(event.dest_path)
    
    def process_pending_events(self):
        """处理待处理的事件"""
        current_time = time.time()
        events_to_process = []
        
        with self.lock:
            # 找出需要处理的事件（延迟超过0.5秒）
            for path, (event_type, timestamp) in list(self.pending_events.items()):
                if current_time - timestamp > 0.5:
                    events_to_process.append((path, event_type))
                    del self.pending_events[path]
        
        # 处理事件
        for path, event_type in events_to_process:
            if os.path.exists(path) and os.path.isfile(path):
                self._log(f"检测到文件变化: {path}")
                self.sync_engine.sync_file(path)


class FileMonitor:
    """文件监控器"""
    
    def __init__(self, sync_engine: SyncEngine, callback: Callable = None):
        self.sync_engine = sync_engine
        self.callback = callback
        self.observer = None
        self.event_handler = None
        self.running = False
        self.process_thread = None
    
    def _log(self, message: str, level: str = "INFO"):
        """记录日志"""
        if self.callback:
            self.callback(message, level)
    
    def _process_pending_events(self):
        """定期处理待处理的事件"""
        while self.running:
            if self.event_handler:
                self.event_handler.process_pending_events()
            time.sleep(0.5)
    
    def start(self):
        """启动文件监控"""
        if self.running:
            self._log("监控已在运行中", "WARNING")
            return
        
        try:
            # 创建事件处理器
            self.event_handler = SyncFileEventHandler(self.sync_engine, self.callback)
            
            # 创建观察者
            self.observer = Observer()
            self.observer.schedule(
                self.event_handler,
                self.sync_engine.source_dir,
                recursive=True
            )
            
            # 启动观察者
            self.observer.start()
            self.running = True
            
            # 启动事件处理线程
            self.process_thread = threading.Thread(target=self._process_pending_events, daemon=True)
            self.process_thread.start()
            
            self._log(f"开始监控目录: {self.sync_engine.source_dir}")
            
        except Exception as e:
            self._log(f"启动文件监控失败: {e}", "ERROR")
            self.running = False
    
    def stop(self):
        """停止文件监控"""
        if not self.running:
            return
        
        self.running = False
        
        if self.observer:
            self.observer.stop()
            self.observer.join(timeout=5)
            self.observer = None
        
        self.event_handler = None
        self._log("文件监控已停止")


